#include "shader.h"
#include "../../base/logger.h"

OPEN_JLIB_NS


void Shader::clear () noexcept {
  if (_id) {
    glDeleteProgram(_id);
    _id = 0;
  }
}

Shader::~Shader () {
  clear();
}

bool Shader::init (const c8* vert, const c8* frag, const c8* geom) {
  GLuint program = glCreateProgram();
  if (!program)
    return false;
  GLuint vid, fid, gid;
  if (!compile(vid, GL_VERTEX_SHADER, vert))
    return false;
  if (!compile(fid, GL_FRAGMENT_SHADER, frag))
    return false;
  if (geom && !compile(gid, GL_GEOMETRY_SHADER, geom))
    return false;
  glAttachShader(program, vid);
  glAttachShader(program, fid);
  if (geom)
    glAttachShader(program, gid);
  glLinkProgram(program);
  glDeleteShader(vid);
  glDeleteShader(fid);
  if (geom)
    glDeleteShader(gid);
  clear();
  _id = program;
  return true;
}

bool Shader::compile (GLuint& shader, GLenum type, const GLchar* source) {
  shader = glCreateShader(type);
  glShaderSource(shader, 1, &source, 0);
  glCompileShader(shader);
  GLint res;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &res);
  if (res != GL_TRUE) {
    auto buf = new(std::nothrow) GLchar[8192];
    glGetShaderInfoLog(shader, 8192, nullptr, buf);
    debug_assert(false, "%s", buf);
    return false;
  }
  return true;
}


CLOSE_JLIB_NS

